//
// Created by yearing on 2021/5/14.
// 题目:设计一个类,我们只能生成该类的一个实例。
// 只能生成一个实例的类是实现了Singleton(单例）模式的类型。由于设计模式在面向对象程序设计中起着举足轻重的作用，在面试过程中很多公司都喜欢问一些与设计模式相关的问题。
// 在常用的模式中，Singleton是准一一个能够用短短几十行代码完整实现的模式。因此，写一个Singleton的类型是一个很常见的面试题。
//
// 心得: 1. 单例实现有2种方式:懒汉和饿汉
// 2.注意线程安全，可以使用std::mutex加锁，可以双检查+锁
// 3.借助call_once单次执行进行分配内存，
// 4. 借助智能指针可以自动释放内存 5.static 成员变量需要在类外实例化
#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

template<typename T>
class Singleton
{
public:
    /// @see https://blog.csdn.net/u011726005/article/details/82356538
    static T* instance() {
        call_once(_once,[&]{
            _data.reset(new T());}
        );
        return  _data.get();
    }

private:
    Singleton();
    ~Singleton();
    static unique_ptr<T> _data;
    static once_flag _once;
};
template<typename T>
unique_ptr<T> Singleton<T>::_data;
template<typename T>
once_flag Singleton<T>::_once;
class A
{
public:
    A():a(10){}
    ~A(){
        cout<<"~A end"<<endl;
    }
    void print(){
        cout<<"A:"<<a<<endl;
    }
private:
    int a;
};

int main()
{
    cout<<"main start"<<endl;
    Singleton<A>::instance()->print();
    Singleton<A>::instance()->print();
    Singleton<A>::instance()->print();
    cout<<"main end"<<endl;
    return 0;
}